package com.fingard.dsp.bank.directbank.weixin01;

import com.fingard.dsp.bank.directConfig.ActSetItem;
import com.fingard.dsp.bank.directbank.FailCode;
import com.fingard.dsp.bank.directbank.PaymentState;
import com.fingard.dsp.bank.directbank.bankInterface.IRealTime;
import com.fingard.dsp.bank.reqrespobj.single.ReqQrySingle;
import com.fingard.dsp.bank.reqrespobj.single.ReqSingle;
import com.fingard.dsp.bank.reqrespobj.single.RetAtsSingle;
import com.fingard.dsp.bank.reqrespobj.single.detail.RetAtsSglDetail;
import com.fingard.text.StringHelper;
import com.fingard.text.XmlHelper;
import com.fingard.xml.XmlTextReader;

import java.util.ArrayList;

/**
 * 微信委托代扣申请扣款提交
 *
 * 参考文档：https://pay.weixin.qq.com/wiki/doc/api/pap.php?chapter=18_3&index=8
 *
 * 业务场景：委托代扣可应用于定期扣款或需事后扣款以期提高效率的场景。例如但不限于，会员制缴费、水电煤缴费、黄钻绿钻增值服务、打车类软件、停车场或高速公路无人缴费、理财通基金定投、信用卡还款等通过用户授权给商户，进行委托扣款的场景。
 * 注：扣费请求首先按签约协议中记录的优先支付方式扣费，否则依次按以下顺序扣费：零钱、信用卡、借记卡
 * 注意：对于自动续费的代扣申请，微信将延迟24小时进行扣款（首次签约可在签约后12小时内立即扣款成功，不受此规则限制）
 *
 * 请求Url https://api.mch.weixin.qq.com/pay/pappayapply
 * 是否需要证书 否
 * 请求方式 post
 * 返回参数说明 扣款接口请求成功，返回success仅代表扣款申请受理成功，不代表扣款成功。扣款是否成功以支付通知的结果为准。
 *
 * @return
 */
public class WEIXIN01RealTime extends WEIXIN01Base implements IRealTime {
    @Override
    public RetAtsSingle d_9108_RealTimeRec(ReqSingle p_req9108) throws Exception {
        RetAtsSingle retAts = new RetAtsSingle(p_req9108.reqHeader);
        RetAtsSglDetail tmpRetDetail = new RetAtsSglDetail();
        tmpRetDetail.reqSeqID = p_req9108.singleDetail.askNumber;

        try {
            ActSetItem actItem = getBankConfig().getActSetItem(p_req9108.singleDetail.recAct, "unifiedorder");
            if (actItem == null) {
                tmpRetDetail.respCode = "0";
                tmpRetDetail.respInfo = "未找到账号:[" + p_req9108.singleDetail.recAct + "]商户配置信息,请检查'config/portfiles/" + p_req9108.reqHeader.bankCode + "/config.xml'中该账号相关商户配置节点是否配置正确!";
                tmpRetDetail.reqSeqID = p_req9108.singleDetail.askNumber;
                tmpRetDetail.transState = PaymentState.FAIL_Payment;
                tmpRetDetail.payInfoCode = FailCode.E9981;
                retAts.writeRetDetail(tmpRetDetail);
                return retAts;
            }

            ArrayList<String> arrayParams = new ArrayList<String>();

            StringBuilder sbXml = new StringBuilder();
            sbXml.append("<xml>\r\n");

            sbXml.append("  <appid>" + actItem.appId + "</appid>\r\n");
            arrayParams.add("appid=" + actItem.appId);

            sbXml.append("  <mch_id>" + actItem.merchantId + "</mch_id>\r\n");
            arrayParams.add("mch_id=" + actItem.merchantId);

            String nonceStr = get_nonce_str();
            sbXml.append("  <nonce_str>" + nonceStr + "</nonce_str>\r\n");
            arrayParams.add("nonce_str=" + nonceStr);

            if (StringHelper.hasAnyChar(p_req9108.singleDetail.memo)) {
                String body = XmlHelper.encode(p_req9108.singleDetail.memo);
                sbXml.append("  <body>" + body + "</body>\r\n");
                arrayParams.add("body=" + body);
            }

            sbXml.append("  <out_trade_no>" + p_req9108.singleDetail.purpose + "</out_trade_no>\r\n");
            arrayParams.add("out_trade_no=" + p_req9108.singleDetail.purpose);

            if (StringHelper.hasAnyChar(p_req9108.singleDetail.payAmount)) {
                String total_fee = StringHelper.amountMultiply100(p_req9108.singleDetail.payAmount);
                sbXml.append("  <total_fee>" + total_fee + "</total_fee>\r\n");
                arrayParams.add("total_fee=" + total_fee);
            }

            String createIp = getBankConfig().getValueAsString("createIp");
            if (StringHelper.hasAnyChar(createIp)) {
                sbXml.append("  <spbill_create_ip>" + createIp + "</spbill_create_ip>\r\n");
                arrayParams.add("spbill_create_ip=" + createIp);
            }

            String notifyUrl = actItem.notifyURLMap.get("entrustRec");
            if (StringHelper.hasAnyChar(notifyUrl)) {
                sbXml.append("  <notify_url>" + notifyUrl + "</notify_url>\r\n");
                arrayParams.add("notify_url=" + notifyUrl);
            }

            sbXml.append("  <trade_type>PAP</trade_type>\r\n");
            arrayParams.add("trade_type=PAP");

            String channelAuthCode = XmlHelper.encode(p_req9108.singleDetail.channelAuthCode);
            if (StringHelper.hasAnyChar(channelAuthCode)) {
                sbXml.append("  <contract_id>" + channelAuthCode + "</contract_id>\r\n");
                arrayParams.add("contract_id=" + channelAuthCode);
            } else {
                channelAuthCode = XmlHelper.encode(p_req9108.singleDetail.sourceNoteCode);
                sbXml.append("  <contract_id>" + channelAuthCode + "</contract_id>\r\n");
                arrayParams.add("contract_id=" + channelAuthCode);
            }

            String[] signParams = new String[arrayParams.size()];
            arrayParams.toArray(signParams);
            String sign = signMessage(signParams, actItem.saltKey);
            sbXml.append("  <sign>" + sign + "</sign>\r\n");
            sbXml.append("</xml>");

            String[] tmpStrRet = sendToBank(sbXml.toString(), "pappayapply");

            if (tmpStrRet[0].length() == 0) {
                StringBuilder tmpSbMsg = new StringBuilder();
                XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1],	tmpSbMsg);
                if (tmpBkReader != null) {
                    String return_code = tmpBkReader.getFirstText("/xml/return_code");
                    String return_msg = tmpBkReader.getFirstText("/xml/return_msg");

                    if (return_code != null && "SUCCESS".equals(return_code)) {
                        tmpRetDetail.respCode = "0";
                        tmpRetDetail.respInfo = tmpBkReader.getFirstText("/xml/return_msg");
                        if (StringHelper.hasAnyChar(tmpBkReader.getFirstText("/xml/err_code_des"))) {
                            tmpRetDetail.respInfo = tmpBkReader.getFirstText("/xml/err_code_des");
                        }
                        tmpRetDetail.transState = tmpBkReader.getFirstText("/xml/result_code");
                        tmpRetDetail.payInfoCode = tmpBkReader.getFirstText("/xml/err_code");
                    } else {
                        tmpRetDetail.respCode = "-1";
                        tmpRetDetail.respInfo = return_msg;
                    }
                } else {
                    tmpRetDetail.respCode = "-1";
                    tmpRetDetail.respInfo = tmpSbMsg.toString();
                }
            } else {
                tmpRetDetail.respCode = "-1";
                tmpRetDetail.respInfo = tmpStrRet[1];
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            tmpRetDetail.respCode = "-1";
            tmpRetDetail.respInfo = ex.getMessage();
            WriteBankLogLn(ex);
        }

        retAts.writeRetDetail(tmpRetDetail);
        return retAts;
    }

/**
 * 微信委托代扣扣款查询提交
 *
 * 参考文档：https://pay.weixin.qq.com/wiki/doc/api/pap.php?chapter=18_3&index=8
 *
 * 业务场景：该接口仅提供微信代扣订单的查询，商户可以通过该接口主动查询微信代扣订单状态，完成下一步的业务逻辑。
 * 注：需要调用查询接口的情况：
 *     当商户后台、网络、服务器等出现异常，商户系统最终未接收到支付通知；
 *     调用支付接口后，返回系统错误或未知交易状态情况；
 *
 * 请求Url https://api.mch.weixin.qq.com/pay/paporderquery
 * 是否需要证书 否
 * 请求方式 post
 *
 * @return
 */
    @Override
    public RetAtsSingle d_9144_QryRealTimeRec(ReqQrySingle p_req9144) throws Exception {
        RetAtsSingle retAts = new RetAtsSingle(p_req9144.reqHeader);
        RetAtsSglDetail tmpRetDetail = new RetAtsSglDetail();
        tmpRetDetail.reqSeqID = p_req9144.askNumber;

        try {
            ActSetItem actItem = getBankConfig().getActSetItem(p_req9144.recAct, "unifiedorder");
            if (actItem != null) {
                ArrayList<String> arrayParams = new ArrayList<String>();

                StringBuilder sbXml = new StringBuilder();
                sbXml.append("<xml>\r\n");

                sbXml.append("  <appid>" + actItem.appId + "</appid>\r\n");
                arrayParams.add("appid=" + actItem.appId);

                sbXml.append("  <mch_id>" + actItem.merchantId + "</mch_id>\r\n");
                arrayParams.add("mch_id=" + actItem.merchantId);

                sbXml.append("  <out_trade_no>" + p_req9144.officePurpose + "</out_trade_no>\r\n");
                arrayParams.add("out_trade_no=" + p_req9144.officePurpose);

                String nonce_str = get_nonce_str();
                sbXml.append("  <nonce_str>" + nonce_str + "</nonce_str>\r\n");
                arrayParams.add("nonce_str=" + nonce_str);

                String[] signParams = new String[arrayParams.size()];
                arrayParams.toArray(signParams);
                String sign = signMessage(signParams, actItem.saltKey);
                sbXml.append("  <sign>" + sign + "</sign>\r\n");
                sbXml.append("</xml>");

                String[] tmpStrRet = sendToBank(sbXml.toString(), "paporderquery");

                if (tmpStrRet[0].length() == 0) {
                    StringBuilder tmpSbMsg = new StringBuilder();
                    XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1],	tmpSbMsg);
                    if (tmpBkReader != null) {
                        String return_code = tmpBkReader.getFirstText("/xml/return_code");
                        String return_msg = tmpBkReader.getFirstText("/xml/return_msg");
                        String result_code = tmpBkReader.getFirstText("/xml/result_code");

                        if (return_code != null && return_code.equals("SUCCESS")) {
                            if (result_code != null	&& result_code.equals("SUCCESS")) {
                                tmpRetDetail.respCode = "0";
                                tmpRetDetail.respInfo = return_msg;
                                String status = tmpBkReader.getFirstText("/xml/trade_state");
                                String statusMsg = tmpBkReader.getFirstText("/xml/trade_state_desc");
                                if ("PAY_FAIL".equals(status)) {
                                    tmpRetDetail.transState = result_code + "+" + status;
                                    tmpRetDetail.payInfoCode = statusMsg;
                                } else {
                                    tmpRetDetail.transState = result_code + "+" + status;
                                    tmpRetDetail.payInfoCode = result_code + "+" + status;
                                }
                                if (StringHelper.hasAnyChar(statusMsg)) {
                                    tmpRetDetail.respInfo = statusMsg;
                                }
                            } else {
                                tmpRetDetail.respCode = "-1";
                                tmpRetDetail.respInfo = tmpBkReader.getFirstText("/xml/return_msg");
                                if (StringHelper.hasAnyChar(tmpBkReader.getFirstText("/xml/err_code_des"))) {
                                    tmpRetDetail.respInfo = tmpBkReader.getFirstText("/xml/err_code_des");
                                }
                                if (tmpRetDetail.respInfo.contains("order not exist")) {
                                    tmpRetDetail.respCode = "0";
                                    tmpRetDetail.transState = result_code + "+" + tmpBkReader.getFirstText("/xml/err_code");
                                    tmpRetDetail.payInfoCode = tmpBkReader.getFirstText("/xml/err_code");
                                }
                            }
                        } else {
                            tmpRetDetail.respCode = "-1";
                            tmpRetDetail.respInfo = return_msg;
                        }
                    } else {
                        tmpRetDetail.respCode = "-1";
                        tmpRetDetail.respInfo = tmpSbMsg.toString();
                    }
                } else {
                    tmpRetDetail.respCode = "-1";
                    tmpRetDetail.respInfo = tmpStrRet[1];
                }
            } else {
                tmpRetDetail.respCode = "-1";
                tmpRetDetail.respInfo = "未找到账号[" + p_req9144.recAct + "]商户配置信息!";
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            tmpRetDetail.respCode = "-1";
            tmpRetDetail.respInfo = ex.getMessage();
            WriteBankLogLn(ex);
        }

        retAts.writeRetDetail(tmpRetDetail);
        return retAts;
    }
}